package com.gopay.bis.service.bank.impl.ebank;

import com.gopay.bis.common.util.TransUtils;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.NuccSerialManager;
import com.gopay.bis.manager.bank.ebank.NuccB2cManager;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.nucc.common.query.res.NuccQueryRes;
import com.gopay.common.domain.bank.nucc.common.refund.res.NuccRefundRes;
import com.gopay.common.domain.bank.nucc.ebank.pay.end.NuccEbankEndRes;
import com.gopay.common.domain.bank.nucc.ebank.pay.res.NuccEbankRes;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.BankInteractRemoteService;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

/**
 * 网联网关支付B2C
 * @NuccB2cBankServiceImpl.java
 * @author zhoutong
 * @2018-1-17 下午1:51:26 www.gopay.com.cn Inc.All rights reserved.
 */
public class NuccB2cBankServiceImpl implements BankInteractRemoteService {

	private static Logger logger = LoggerFactory.getLogger(NuccB2cBankServiceImpl.class);

	@Resource(name = "nuccB2cManager")
	private NuccB2cManager nuccB2cManager;

	@Resource(name = "nuccSerialManager")
	private NuccSerialManager nuccSerialManager;

	@Resource(name = "bankOrderManager")
	private BankOrderManager bankOrderManager;

	@Override
	public Result pay(BaseMessage base) {
		Result result = new Result(false);
		try {
			nuccSerialManager.generateFlowIdBySerial(base, true, NuccConstants.NUCC_SERIAL_CONTROL_GW);
			NuccEbankRes res = (NuccEbankRes) nuccB2cManager.sign(base);
			if (!NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())) {
				logger.error("网联网关支付申请异常，系统返回码为"+res.getMsgBody().getSysRtnInf().getSysRtnCd()+":"+res.getMsgBody().getSysRtnInf().getSysRtnDesc());
				nuccSerialManager.getFlowIdRule();
				throw new GopayException(res.getMsgBody().getSysRtnInf().getSysRtnCd(),res.getMsgBody().getSysRtnInf().getSysRtnDesc());
			}
			if (!NuccConstants.NUCC_BIZSTSCD_SUCCESS.equals(res.getMsgBody().getBizInf().getBizStsCd())) {
				logger.error("网联网关支付申请异常，业务返回码为"+res.getMsgBody().getBizInf().getBizStsCd()+":"+res.getMsgBody().getBizInf().getBizStsDesc());
				throw new GopayException(res.getMsgBody().getBizInf().getBizStsCd(),res.getMsgBody().getBizInf().getBizStsDesc());
			}
			if (!NuccConstants.NUCC_TRXSTATUSCD_PROCESSING.equals(res.getMsgBody().getBizInf().getTrxStatus())) {
				logger.error("网联网关支付申请异常，交易状态为"+res.getMsgBody().getBizInf().getTrxStatus());
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E6128);
			}
			res.setSignMessage(Base64.encodeBase64String(StringUtils.getBytesUtf8(res.getPlainMessage())));
			base.setSignMessage(res.getSignMessage());
			BeanUtils.copyProperties(base, res);
			result.setDefaultModel(res);
			result.setSuccess(true);
		} catch (GopayException e) {
			logger.error("nucc b2c exception：", e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			logger.error("nucc b2c exception：", ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6128);
		}
		return result;
	}

	@Override
	public Result bankBack(BaseMessage base) {
		Result result = new Result(false);
		try {
			NuccEbankEndRes stream = (NuccEbankEndRes) nuccB2cManager.verify(base);
			stream.setBankOrderId(stream.getMsgBody().getBizInf().getTrxId());
			BankOrder bankOrder = bankOrderManager.getBankOrderById(stream.getBankOrderId());
			stream.setOrderId(bankOrder.getOrderId());
			String amout = stream.getMsgBody().getBizInf().getTrxAmt();
			stream.setAmount(new BigDecimal(amout.substring(3)));
			//付款行流水号
			String dbtrBankId = stream.getMsgBody().getBizInf().getDbtrBankId();
			stream.setBankIntrChann(base.getBankIntrChann());
			stream.setSpecial4(dbtrBankId);
			stream.setFront(base.isFront());
			stream.setBank(base.getBank());
			stream.setBankBusProd(base.getBankBusProd());
			result.setDefaultModel(stream != null ? true : false);
			result.setModel("res", stream);
			result.setSuccess(true);

			Map<String, String> param = new HashMap<String, String>();
			String trxStatus = stream.getMsgBody().getBizInf().getTrxStatus();//状态
			// 验签成功入账
			if (NuccConstants.NUCC_TRXSTATUSCD_SUCCESS.equals(trxStatus)
					|| NuccConstants.NUCC_EXCEPTION_SUCCESS.equals(trxStatus)) {
				// 如果该订单成功通知后台地址入账
				param.put("orderId", stream.getOrderId());
				param.put("amt", stream.getAmount().toString());
				param.put("cardType", "Unknown");
				param.put("notifyNum", "1");
				param.put("payStatus", "00");
				param.put("retCode", "00");
				param.put("retMsg", "");
				param.put("signData", base.getSignMessage());
				param.put("isFront", base.isFront() + "");
				result.setModel("isNotifyCashier", param);
				result.setOrderStatus(true);
			} else {
				// 通知后台地址该订单失败
				param.put("orderId", stream.getOrderId());
				param.put("amt", stream.getAmount().toString());
				param.put("cardType", "Unknown");
				param.put("notifyNum", "1");
				param.put("payStatus", "01");
				param.put("retCode", "01");
				param.put("retMsg", "");
				param.put("signData", base.getSignMessage());
				param.put("isFront", base.isFront() + "");
				result.setModel("isNotifyCashier", param);
				result.setOrderStatus(false);
			}

		} catch (GopayException e) {
			logger.error("NuccB2cBankServiceImpl Exception：", e);
			result.setResultCode(e.getErrCode());
		} catch (Exception e) {
			logger.error("NuccB2cBankServiceImpl Exception：", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6064);
		}
		return result;
	}

	@Override
	public Result queryBack(BaseMessage base) {
		return null;
	}

	@Override
	public Result query(BaseMessage base) {
		Result result = new Result(false);
		try {
			NuccQueryRes res = (NuccQueryRes) nuccB2cManager.queryOrder(base);
			BeanUtils.copyProperties(base, res);
			result.setDefaultModel(res);
			result.setSuccess(true);
		} catch (GopayException e) {
			logger.error("nucc b2c query exception：", e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			logger.error("nucc b2c query exception：", ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6131);
		}
		return result;
	}

	@Override
	public Result refund(BaseMessage base) {
		Result result = new Result(false);
		try {
			NuccRefundRes res = (NuccRefundRes) nuccB2cManager.refund(base);
			BeanUtils.copyProperties(base, res);
			result.setSuccess(true);
		} catch (GopayException e) {
			logger.error("nucc b2c refund Exception：", e);
			result.setResultCode(e.getErrCode());
		} catch (Exception e) {
			logger.error("nucc b2c refund Exception：", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
		}
		return result;
	}

	@Override
	public Result sendBankRefund(BaseMessage base) {
		return null;
	}

	@Override
	public Result dayend(BaseMessage base) {
		return null;
	}

	@Override
	public Result refundBack(BaseMessage base) {
		return null;
	}

	@Override
	public Result refundQuery(BaseMessage base) {
		return null;
	}
}
